package models

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"sync"
	"time"

	"github.com/gorilla/websocket"
	"gopkg.in/fatih/set.v0"
	"gorm.io/gorm"
)

type Message struct {
	gorm.Model
	FormId     string //谁发送的消息
	TargetId   int64  //谁收信息
	Type       int    //发送类型  1私聊  2群聊  3心跳
	Media      int    //消息类型  1文字 2表情包 3语音 4图片 /表情包
	Content    string //消息内容
	CreateTime uint64 //创建时间
	Pic        string
	Url        string
	Desc       string
	Amount     int //其他数字统计
}

func (table *Message) TableName() string {
	return "message_allpeople"
}

const (
	HeartbeatMaxTime = 1 * 60
)

type Node struct {
	Conn          *websocket.Conn //连接
	Addr          string          //客户端地址
	FirstTime     uint64          //首次连接时间
	HeartbeatTime uint64          //心跳时间
	LoginTime     uint64          //登录时间
	DataQueue     chan []byte     //消息
	GroupSets     set.Interface   //好友 / 群
}

// 映射关系
var clientMap map[int64]*Node = make(map[int64]*Node, 0)

// 读写锁
var rwLocker sync.RWMutex

func Chat(writer http.ResponseWriter, request *http.Request) {
	//1检验token
	query := request.URL.Query()
	Id := query.Get("userId")
	userId, _ := strconv.ParseInt(Id, 10, 64)
	//Parse的意思是解释为 这一点在下面的IP地址依然适用
	TargetId := query.Get("targetId")
	fmt.Println(TargetId)

	//这里为什么一开始是true
	isvalid := true
	//这里已经得到了从websocket得到了的conn
	conn, err := (&websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return isvalid
		},
	}).Upgrade(writer, request, nil)
	if err != nil {
		fmt.Println(err)
		return
	}

	//2初始化node
	node := &Node{
		Conn:      conn,
		DataQueue: make(chan []byte, 50),
		GroupSets: set.New(set.ThreadSafe),
	}

	//3.建立用户关系
	//4.userId和conn连接在一起
	rwLocker.Lock()
	clientMap[userId] = node
	rwLocker.Unlock()
	//5.完成发送逻辑
	go sendProc(node)
	//6.完成接受逻辑
	go recvProc(node)
	fmt.Printf("ss")
}

// 这里是发信息给websocket
func sendProc(node *Node) {
	for {
		select {
		case data := <-node.DataQueue:
			fmt.Println("[ws]SendProc。。。。", string(data))
			err := node.Conn.WriteMessage(websocket.TextMessage, data)
			if err != nil {
				fmt.Println(err)
				return
			}
		}
	}
}

func recvProc(node *Node) {
	for {
		_, data, err := node.Conn.ReadMessage()
		if err != nil {
			fmt.Println(err)
			return
		}
		//这个broadMsg是把信息给所有人
		broadMsg(data)
	}
}

var udpsendChan chan []byte = make(chan []byte, 1024)

func broadMsg(data []byte) {
	udpsendChan <- data
}

// 这里是发信息
func UDPsentMsg() {
	conn, err := net.DialUDP("DialUDP", nil, &net.UDPAddr{
		IP:   net.ParseIP("100.64.96.174"),
		Port: 8080,
	})
	if err != nil {
		// 处理错误
		fmt.Println(err)
	}
	fmt.Println(conn.LocalAddr().Network())

}

func dispatch(data []byte) {
	msg := Message{}
	//后端调度逻辑
	msg.CreateTime = uint64(time.Now().Unix())
	//把内容解JSON码 是为了获得其中的信息类型
	err := json.Unmarshal(data, &msg)
	if err != nil {
		log.Fatal(err)
	}
	switch msg.Type {
	case 1: //私信
		sendMsg(msg.TargetId, data)
	case 2: //群发
		sendGroupMsg(msg.TargetId, data)
	}
}

func sendMsg(userId int64, msg []byte) {
	//发信息先锁住再发
	rwLocker.Lock()
	//这里获取的是通过userId得到node
	node, ok := clientMap[userId]
	rwLocker.Unlock()
	Jsonmsg := Message{}
	json.Unmarshal(msg, &Jsonmsg)
	if ok {
		node.DataQueue <- msg
	}
	panic("unimplemented")
}

func sendGroupMsg(s int64, data []byte) {
	panic("unimplemented")
}
